#pragma once
#include "Common.hpp"
#include "InetAddr.hpp"
#include "Socket.hpp"
#include <sstream>
#include <memory>
#include <functional>
#include <jsoncpp/json/json.h>

class Request
{
public:
	Request() {}
	Request(int x, int y, char op)
		: _x(x), _y(y), _op(op) {}
	std::string Serialize()
	{
		Json::Value root;
		root["x"] = _x;
		root["y"] = _y;
		root["op"] = std::string(1, _op);

		Json::FastWriter writer;
		std::string str = writer.write(root);
		return str;
	}

	bool Deserialize(std::string &in)
	{
		Json::Reader reader;
		Json::Value root;
		bool ok = reader.parse(in, root);
		if (!ok)
		{
			LOG(LogLevel::ERROR) << "json parse error";
			return false;
		}

		_x = root["x"].asInt();
		_y = root["y"].asInt();
		_op = root["op"].asString()[0];

		return true;
	}

	int X() const
	{
		return _x;
	}

	int Y() const
	{
		return _y;
	}

	char Op() const
	{
		return _op;
	}

private:
	int _x;	  // 10
	int _y;	  // 20
	char _op; // +
};

class Response
{
public:

	Response()
	{
		_result = -1;
		_code = -1;
	}
	std::string Serialize()
	{
		Json::Value root;
		root["result"] = _result;
		root["code"] = _code;

		Json::FastWriter writer;
		std::string str = writer.write(root);
		return str;
	}

	void Deserialize(std::string &in)
	{
		Json::Value root;
		Json::Reader reader;
		bool ok = reader.parse(in, root);
		if (!ok)
		{
			LOG(LogLevel::ERROR) << "json parse error";
			return;
		}

		_result = root["result"].asInt();
		_code = root["code"].asInt();
	}

	void SetResult(int result)
	{
		_result = result;
	}

	void SetCode(int code)
	{
		_code = code;
	}

	void ShowResult()
	{
		std::cout << "result: " << _result << std::endl;
		if (!_code)
			std::cout << "退出码为0，计算结果正确" << std::endl;
		else
			std::cout << "退出码为" << _code << "，计算结果错误" << std::endl;
	}

private:
	int _result;
	int _code; // 根据退出码判断计算是否有误
};

using func_t = std::function<Response(Request &)>;
const std::string sep = "\r\n";

class Protocol
{
public:
	Protocol() {}
	Protocol(func_t func) : _func(func) {}

	// 封装报文
	// 20\r\n{"x":10,"y":20,"oper":"+"}\r\n
	std::string Encode(const std::string &jsonstr)
	{
		std::string len = std::to_string(jsonstr.size());
		std::string final_str = len + sep + jsonstr + sep;
		return final_str;
	}

	// 解析报文
	bool Decode(std::string &buffer, std::string &package)
	{
		int pos = buffer.find(sep);
		if (pos == std::string::npos)
		{
			// 连分隔符都没找到，说明不是一个完整的报文
			return false;
		}

		// 解析实际内容报文长度
		std::string package_len_str = buffer.substr(0, pos);
		int package_len = std::stoi(package_len_str);

		int total_len = package_len_str.size() + sep.size() + package_len + sep.size();
		if (buffer.size() < total_len)
		{
			// 说明报文不完整
			return false;
		}

		package = buffer.substr(pos + sep.size(), package_len);
		buffer.erase(0, total_len);

		return true;
	}
	void GetRequest(std::unique_ptr<Socket> &sock, InetAddr &client)
	{
		std::string buffer;
		while (true)
		{
			// 接收信息
			int n = sock->Recv(&buffer);
			if (n <= 0)
			{
				LOG(LogLevel::INFO) << "Client " << client.StringAddr() << " closed connection.";
				break;
			}

			// 解析报文
			while (true)
			{
				std::string package;
				bool ret = Decode(buffer, package);
				if (!ret)
					break;

				Request req;
				bool ok = req.Deserialize(package);
				if (!ok)
					continue;

				// 执行业务逻辑
				Response resp = _func(req);

				// 序列化
				std::string json_str = resp.Serialize();

				// 封装并发送
				std::string send_str = Encode(json_str);
				sock->Send(send_str);
			}
		}
	}

	bool GetResponse(std::unique_ptr<Socket> &client, std::string &resp_buffer, Response &resp)
	{
		while(true){
			std::string json_str;
			if(Decode(resp_buffer, json_str)){
				// buffer 中已经有一个完整的包，直接处理
				resp.Deserialize(json_str);
				return true;
			}

            // buffer 中没有完整包，需要继续接收
			int n = client->Recv(&resp_buffer);
			if(n <= 0){
				return false; // 连接关闭或出错
			}
			// 接收到新数据后，循环会回到开始，再次尝试 Decode
		}
		return false; // 理论上不会执行到这里
	}

	std::string BulidRequestString(int x, int y, char op)
	{
		Request req(x, y, op);

		// 序列化
		std::string json_req = req.Serialize();
		return Encode(json_req);
	}

private:
	func_t _func;
};